#include <stdio.h>

#define EPSILON ""
#define IS_EPSILON(s) ((s)[0] == '\0')

#define EMPTY_SET(s) (empty_set(&(s)))
#define EMPTY_RULESET(s) (empty_ruleset(&(s)))

typedef char * symbol;
typedef struct llist_sym * * set;
typedef struct rule * rule;
typedef struct llist_rul * * ruleset;

struct llist_sym
{
  symbol value;
  struct llist_sym * next;
};

struct rule
{
  symbol nonterm;
  int num_components;
  symbol * components;
};

struct llist_rul
{
  rule r;
  struct llist_rul * next;
};

void set_free(set *);
void ruleset_free(ruleset *);
int set_size(set);
int ruleset_size(ruleset);
void build_first_sets(symbol[], int, rule[], int, set[]);
void build_follow_sets(symbol[], int, rule[], int, const set[], set[]);
void build_table(symbol[], int, symbol[], int, const rule[], int,
                 const set[], const set[], ruleset *);
void print_table(const ruleset *, int, int, symbol[], FILE *);
void print_set(set, FILE*);
int set_add(set, symbol);
int ruleset_add(ruleset, rule);
void empty_set(set *);
void empty_ruleset(ruleset *);
int set_contains(set, symbol);
